package biz.datalk.industrialland.admin.modules.system.service.impl;

import biz.datalk.industrialland.admin.component.shiro.CustomLoginUser;
import biz.datalk.industrialland.admin.modules.system.mapper.ISysDepartExtMapper;
import biz.datalk.industrialland.admin.modules.system.pojo.dto.SysDepartDTO;
import biz.datalk.industrialland.admin.modules.system.pojo.vo.SysDepartVO;
import biz.datalk.industrialland.admin.modules.system.service.ISysDepartService;
import biz.datalk.industrialland.admin.modules.system.util.GenCodeUtil;
import biz.datalk.industrialland.admin.modules.util.ShiroUtil;
import biz.datalk.industrialland.common.def.enums.DBYNEnum;
import biz.datalk.industrialland.common.exception.ServiceException;
import biz.datalk.industrialland.common.result.UnifyResult;
import biz.datalk.industrialland.common.util.EntityIdUtils;
import biz.datalk.industrialland.common.util.I18NUtil;
import biz.datalk.industrialland.mbg.mapper.SysDepartMapper;
import biz.datalk.industrialland.mbg.pojo.po.SysDepart;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author tarofang@163.com
 * @date 2019-09-08
 */
@Slf4j
@Service
public class SysDepartServiceImpl implements ISysDepartService {

    private final SysDepartMapper sysDepartMapper;

    private final ISysDepartExtMapper sysDepartExtMapper;

    @Autowired
    public SysDepartServiceImpl(SysDepartMapper sysDepartMapper, ISysDepartExtMapper sysDepartExtMapper) {
        this.sysDepartMapper = sysDepartMapper;
        this.sysDepartExtMapper = sysDepartExtMapper;
    }

    @Override
    public UnifyResult list(SysDepartDTO sysDepartDTO) {

        QueryWrapper<SysDepart> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc(SysDepart.COL_UPDATE_TIME);

        IPage<SysDepart> page = new Page<>(sysDepartDTO.getPageNumber(), sysDepartDTO.getPageSize());
        IPage<SysDepart> pageInfo = sysDepartMapper.selectPage(page, queryWrapper);

        return UnifyResult.success().mapData().put("rows", pageInfo.getRecords()).put("total", pageInfo.getTotal());

        // SysDepartExample example = new SysDepartExample();
        // example.setOrderByClause("update_time DESC");
        //
        // PageHelper.startPage(sysDepartDTO.getPageNumber(), sysDepartDTO.getPageSize());
        // List<SysDepart> userList = sysDepartMapper.selectByExample(example);
        // PageInfo<SysDepart> pageInfo = new PageInfo<SysDepart>(userList);
        // return UnifyResult.success().mapData().put("rows", pageInfo.getList()).put("total", pageInfo.getTotal());
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public UnifyResult add(SysDepartDTO sysDepartDTO) {
        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();
        Integer departType = sysDepartDTO.getDepartType();
        if (departType != 1 && departType != 2) {
            throw new ServiceException("未知的部门类型");
        }

        String orgCode = "";
        int departLevel;
        // 机构类型 1一级部门 2子部门
        if (departType == 2) {
            Long pid = sysDepartDTO.getPid();
            SysDepart parent = sysDepartMapper.selectById(pid);
            if (parent == null) {
                throw new ServiceException("父节点不存在或已被删除");
            }
            orgCode = genOrgCode(pid);
            departLevel = Optional.ofNullable(parent.getDepartLevel()).orElse(1) + 1;

        } else {
            sysDepartDTO.setPid(0L);
            orgCode = genOrgCode(null);
            departLevel = 1;
        }

        Date now = new Date();

        SysDepart sysDepart = new SysDepart();
        sysDepart.setPid(sysDepartDTO.getPid());
        sysDepart.setDepartName(sysDepartDTO.getDepartName());
        sysDepart.setDepartNameEn(sysDepartDTO.getDepartNameEn());
        sysDepart.setDepartNameAbbr(sysDepartDTO.getDepartNameAbbr());
        sysDepart.setDepartType(departType);
        sysDepart.setDepartCode(orgCode);
        sysDepart.setDepartLevel(departLevel);
        sysDepart.setDepartOrder(sysDepartDTO.getDepartOrder());
        sysDepart.setDescription(sysDepartDTO.getDescription());
        sysDepart.setIsValid(DBYNEnum.Y.name());
        sysDepart.setIsDelete(DBYNEnum.N.name());
        sysDepart.setCreateBy(customLoginUser.getId());
        sysDepart.setCreateName(customLoginUser.getRealname());
        sysDepart.setCreateTime(now);
        sysDepart.setUpdateBy(0L);
        sysDepart.setUpdateName(StringUtils.EMPTY);
        sysDepart.setUpdateTime(now);

        sysDepartMapper.insertSelective(sysDepart);
        return UnifyResult.success().setData(sysDepart.getId());
    }

    @Override
    public String genOrgCode(Long pid) {
        pid = pid == null ? 0L : pid;
        // 一级部门
        if (pid == 0) {
            List<SysDepart> deptList = sysDepartExtMapper.selectByPidOrderDepartCodeDesc(0L);
            // 没有一级部门
            if (CollectionUtils.isEmpty(deptList)) {
                return GenCodeUtil.getNextOrgCode(null);
            }

            // 有一级部门
            SysDepart depart = deptList.get(0);
            String departCode = depart.getDepartCode();
            return GenCodeUtil.getNextOrgCode(departCode);
        }

        // 查询出父级部门
        SysDepart parent = sysDepartMapper.selectById(pid);
        String parentCode = parent.getDepartCode();

        // 子部门
        List<SysDepart> deptList = sysDepartExtMapper.selectByPidOrderDepartCodeDesc(pid);

        // 没有子部门
        if (CollectionUtils.isEmpty(deptList)) {
            String subCode = parentCode + GenCodeUtil.getNextOrgCode(null);
            // GenCodeUtil.getSubOrgCodeV2(parentCode);
            if (!subCode.startsWith(parentCode)) {
                log.warn("Department has been removed. [pid={}, parentCode={}, subCode={}]", parent.getId(), parentCode, subCode);
            }
            return subCode;
        }

        // 有子部门
        SysDepart depart = deptList.get(0);
        String nextOrgCode = GenCodeUtil.getNextOrgCode(depart.getDepartCode());
        if (!nextOrgCode.startsWith(parentCode)) {
            log.warn("Department has been removed. [pid={}, parentCode={}, nextOrgCode={}]", parent.getId(), parentCode, nextOrgCode);
        }
        return nextOrgCode;
    }

    @Override
    public List<SysDepartVO> treeAll(SysDepartDTO sysDepartDTO) {
        List<SysDepartVO> res = sysDepartExtMapper.selectAllValid();
        res = res == null ? new ArrayList<>() : res;
        // 获取树
        List<SysDepartVO> orgs = pkgTreeData(res, null);
        // 排序
        treeDataSort(orgs, false);

        return orgs;
    }

    private void treeDataSort(List<SysDepartVO> orgs, final boolean isDesc) {
        if (CollectionUtils.size(orgs) > 1) {
            orgs.sort((a, b) -> isDesc ? b.getDepartOrder().compareTo(a.getDepartOrder()) : a.getDepartOrder().compareTo(b.getDepartOrder()));
        }
        List<SysDepartVO> sub;
        for (SysDepartVO org : orgs) {
            sub = org.getSub();
            treeDataSort(sub, isDesc);
            org.setSub(sub);
        }
    }

    @Override
    public List<SysDepartVO> pkgTreeData(List<SysDepartVO> list, SysDepartVO parent) {
        List<SysDepartVO> orgs = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return orgs;
        }
        // 1-一级部门 2-子部门
        int departType = parent == null ? 1 : 2;
        for (SysDepartVO vo : list) {
            if (vo.getDepartType() != departType) {
                continue;
            }
            // 一级部门
            if (parent == null) {
                vo.setSub(pkgTreeData(list, vo));
                vo.setHasSub(CollectionUtils.isNotEmpty(vo.getSub()));
                orgs.add(vo);
                continue;
            }
            // 子部门
            if (Objects.equals(vo.getPid(), parent.getId())) {
                vo.setSub(pkgTreeData(list, vo));
                vo.setHasSub(CollectionUtils.isNotEmpty(vo.getSub()));
                orgs.add(vo);
            }
        }

        return orgs;
    }


    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public UnifyResult update(SysDepartDTO sysDepartDTO) {
        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();
        Long id = sysDepartDTO.getId();
        SysDepart exists = sysDepartMapper.selectById(id);
        if (exists == null) {
            return UnifyResult.fail(I18NUtil.getMsg("depart.no.exists.or.delete"));
        }

        SysDepart record = new SysDepart();
        record.setId(id);
        record.setDepartName(sysDepartDTO.getDepartName());
        record.setDepartNameEn(sysDepartDTO.getDepartNameEn());
        record.setDepartNameAbbr(sysDepartDTO.getDepartNameAbbr());
        record.setDescription(sysDepartDTO.getDescription());
        record.setDepartOrder(sysDepartDTO.getDepartOrder());
        record.setUpdateBy(customLoginUser.getId());
        record.setUpdateName(customLoginUser.getRealname());
        record.setUpdateTime(new Date());

        sysDepartMapper.updateByPrimaryKeySelective(record);
        return UnifyResult.success();
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public UnifyResult batchDelete(SysDepartDTO sysDepartDTO) {
        List<Long> sysids = EntityIdUtils.parseIds(sysDepartDTO.getSysids());

        SysDepart params = new SysDepart();
        long currentUserId = ShiroUtil.getCurrentUserId();
        params.setUpdateBy(currentUserId);
        params.setUpdateTime(new Date());
        params.setIsDelete(DBYNEnum.Y.name());
        params.setIsValid(DBYNEnum.N.name());


        UpdateWrapper<SysDepart> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in(SysDepart.COL_ID, sysids);
        int resInt = sysDepartMapper.update(params, updateWrapper);
        if (resInt != CollectionUtils.size(sysids)) {
            throw new ServiceException(I18NUtil.getMsg("depart.batch.delete.fail"));
        }

        // SysDepartExample example = new SysDepartExample();
        // // example.createCriteria().andIdIn(sysids);
        //
        // int resInt = sysDepartMapper.updateByExampleSelective(params, example);
        // if (resInt != CollectionUtils.size(sysids)) {
        //     throw new ServiceException(I18NUtil.getMsg("depart.batch.delete.fail"));
        // }

        return UnifyResult.success();
    }

    @Override
    public List<SysDepartVO> tree(SysDepartDTO sysDepartDTO) {
        Long pid = sysDepartDTO.getPid();
        pid = Optional.ofNullable(pid).orElse(0L);
        List<SysDepartVO> res = sysDepartExtMapper.selectByPid(pid);
        res = CollectionUtils.isEmpty(res) ? new ArrayList<>() : res;
        return res;
    }

    @Override
    public void delete(SysDepartDTO sysDepartDTO) {
        long id = sysDepartDTO.getId();
        SysDepart exists = sysDepartMapper.selectById(id);
        if (exists == null) {
            throw new ServiceException("部门不存在或已经被删除");
        }
        // 判定是否有子节点 有子节点的不能删除
        List<SysDepartVO> res = sysDepartExtMapper.selectByPid(id);
        if (CollectionUtils.isNotEmpty(res)) {
            throw new ServiceException("部门中存在子部门，不能直接删除");
        }

        // TODO 判定是否在使用 使用中的不能删除

        int resInt = sysDepartMapper.deleteById(id);
        if (resInt != 1) {
            throw new ServiceException("删除失败");
        }
    }
}
